package db_live

import (
	"errors"
	"fmt"
	"longmen/server/config/global"
	"longmen/server/pkg/db/mysql/models/models_live"
	"longmen/server/pkg/db/mysql/models/models_main"
	"time"

	"gorm.io/datatypes"
	"gorm.io/gorm"
)

// 给指定用户列表发放观赛券
func ProvideTicket(uids []int64, quantity int, provideType int) error {
	if quantity <= 0 || len(uids) == 0 {
		return fmt.Errorf("invalid input")
	}

	type key struct {
		Uid  int64
		Type int
	}

	tx := global.GetR().Begin()
	var err error
	defer func() {
		if err != nil {
			tx.Rollback()
		}
	}()

	// 查询已有记录
	var existing []models_main.UserBackpackStatistics
	if err = tx.Where("uid IN ? AND type = ?", uids, 105).Find(&existing).Error; err != nil {
		return fmt.Errorf("query existing failed: %w", err)
	}

	existingMap := make(map[int64]models_main.UserBackpackStatistics)
	for _, item := range existing {
		existingMap[int64(item.Uid)] = item
	}

	var toInsert []models_main.UserBackpackStatistics
	var toUpdate []int // 只保留 UID 供构造 SQL 用

	// 增加发放记录
	userTicketLogs := make([]*models_main.DbUserTicketLog, 0)

	for _, uid := range uids {
		if _, found := existingMap[uid]; found {
			toUpdate = append(toUpdate, int(uid))
		} else {
			toInsert = append(toInsert, models_main.UserBackpackStatistics{
				Uid:          int(uid),
				Type:         105,
				Gid:          9,
				Selected:     1,
				Price:        0,
				Quantity:     quantity,
				ProductName:  "观赛券",
				UsedQuantity: 0,
			})
		}
		//构造发放记录
		userTicketLogs = append(userTicketLogs, &models_main.DbUserTicketLog{
			UID:        int(uid),
			Num:        quantity,
			Date:       datatypes.Date(time.Now()),
			CreateTime: time.Now(),
			Type:       int8(provideType),
		})
	}

	// 批量插入
	if len(toInsert) > 0 {
		if err = tx.Create(&toInsert).Error; err != nil {
			return fmt.Errorf("batch insert failed: %w", err)
		}
	}

	if len(toUpdate) > 0 {
		err = tx.Model(&models_main.UserBackpackStatistics{}).Where("uid in ? and type=105", toUpdate).Update("quantity", gorm.Expr("quantity+?", quantity)).Error
		if err != nil {
			return errors.New("门票入场发券失败")
		}
	}

	if len(userTicketLogs) > 0 {
		err = tx.Model(&models_main.DbUserTicketLog{}).Create(userTicketLogs).Error
		if err != nil {
			return err
		}
	}

	if err = tx.Commit().Error; err != nil {
		return err
	}

	return nil
}

func TicketLog(r *models_live.LiveTicketLog) error {
	var err error
	var ticketNum int = 0
	err = global.GetR().Model(&models_main.UserBackpackStatistics{}).Where("uid=? and type=105", r.UID).Pluck("quantity", &ticketNum).Error
	if err != nil || ticketNum < r.Ticket {
		return errors.New("入场券数量不足")
	}

	tx := global.Live().Begin()
	propsTx := global.GetR().Begin()
	err = tx.Model(&models_live.LiveTicketLog{}).Create(&r).Error
	if err != nil {
		tx.Rollback()
		propsTx.Rollback()
		return errors.New("门票入场失败")
	}

	err = propsTx.Model(&models_main.UserBackpackStatistics{}).Where("uid=? and type=105", r.UID).Update("quantity", gorm.Expr("quantity-?", r.Ticket)).Error
	if err != nil {
		tx.Rollback()
		propsTx.Rollback()
		return errors.New("门票入场扣除失败")
	}

	tx.Commit()
	propsTx.Commit()

	return nil
}

func TicketINLive(uid int, liveid int64, ticketSwitch int) (bool, error) {
	// config := cache2.GetConfigPub()
	// 观赛券开关  1开启 0关闭 不消耗观赛券
	if ticketSwitch == 0 {
		return true, nil
	}

	// return false
	// old 每个直播间用一张
	// var id int = 0
	// err := global.Live().Model(&models_live.LiveTicketLog{}).Where("uid=? and liveid=?", uid, liveid).Pluck("id", &id).Error
	// if id == 0 || err != nil {
	// 	return false
	// }
	// new 规定时间内24小时任意直播间只消耗一张 false消耗 true不消耗
	ticketLog := &models_live.LiveTicketLog{}
	if err := global.Live().Model(&models_live.LiveTicketLog{}).Where("uid =?", uid).Order("created_at desc").Last(&ticketLog).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return false, nil
		}
		global.Log.Errorf("获取用户是否使用过入场券失败:%v", err)
		return true, errors.New("获取用户是否使用过入场券失败")
	}

	// 券超过24小时需要从新消耗
	if (time.Now().Unix() - ticketLog.CreatedAt) > 86400 {
		return false, nil
	}

	return true, nil
}

func TicketINLives(uid int, liveids []int64) []models_live.LiveTicketLog {
	var res []models_live.LiveTicketLog

	global.Live().Model(&models_live.LiveTicketLog{}).Where("uid=?", uid).Where("liveid", liveids).Find(&res)

	return res
}

// 观看卷使用记录
func TicketList(uid, status, page, size int) ([]*models_live.LiveTicketLog, int64, int64, error) {
	tx := global.Live().Model(&models_live.LiveTicketLog{}).Where("uid = ?", uid)

	// 获取用户未使用的观看卷数量
	var unUse int64
	userBackpackStatistic := &models_main.UserBackpackStatistics{}
	if err := global.GetX().Model(&models_main.UserBackpackStatistics{}).Where("uid = ? and type = ?", uid, 105).Take(userBackpackStatistic).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			unUse = 0
		}
		global.Log.Errorf("获取用户未使用入场券失败:%v", err)
		return nil, 0, unUse, errors.New("获取用户未使用入场券失败")
	}

	unUse = int64(userBackpackStatistic.Quantity)

	ticketLogs := make([]*models_live.LiveTicketLog, 0)
	var total int64
	now := time.Now()
	// 获取使用中的观看券
	if status == 1 {
		ticketLog := &models_live.LiveTicketLog{}
		if err := tx.Order("created_at desc").Last(&ticketLog).Error; err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return nil, 0, unUse, nil
			}
			global.Log.Errorf("获取用户使用中入场券失败:%v", err)
			return nil, 0, unUse, errors.New("获取用户使用中入场券失败")
		}

		// 券超过24小时需要从新消耗
		if (now.Unix() - ticketLog.CreatedAt) > 86400 {
			return nil, 0, unUse, nil
		}

		ticketLogs = append(ticketLogs, ticketLog)
		total = 1
		// 获取已使用的观看券
	} else if status == 2 {
		tx = tx.Where("created_at <= ?", now.Unix()-86400)
		if page == 0 {
			page = 1
		}
		if size == 0 {
			size = 10
		}

		offset := (page - 1) * size
		tx = tx.Count(&total).Offset(offset).Limit(size)
		if err := tx.Order("created_at desc").Find(&ticketLogs).Error; err != nil {
			global.Log.Errorf("获取用户已使用入场券失败:%v", err)
			return nil, 0, unUse, errors.New("获取用户已用中入场券失败")
		}
	} else if status == 0 {
		if page == 0 {
			page = 1
		}
		if size == 0 {
			size = 10
		}
		offset := (page - 1) * size
		tx = tx.Count(&total).Offset(offset).Limit(size)
		if err := tx.Order("created_at desc").Find(&ticketLogs).Error; err != nil {
			global.Log.Errorf("获取所有观看券失败:%v", err)
			return nil, 0, unUse, errors.New("获取用户所有观看券失败")
		}
	}

	return ticketLogs, total, unUse, nil
}
